import { useCommon } from "@/hooks/useCommon";
import { useChat } from "@/store/modules/chat";
import { useUser } from "@/store/modules/user";
import { ChatType, IFile, IMessage, MessageStatus, MessageType, TacticMessageType } from "@/types/chat";
import { Ref } from "vue";
import { upload } from "@/api";
import { Base64ToFile, CheckFileSize } from "@/utils/file";
import { GenerateStringUUid } from "@/utils/common";
import { AxiosProgressEvent } from "axios";
import { CallStatus } from "@/types/call";

type UploadProgress = {
  onUploadProgress?: (event: AxiosProgressEvent) => void;
  onDownloadProgress?: (event: AxiosProgressEvent) => void;
};

type MergeDataParams = Partial<IMessage> & Required<Pick<IMessage, "sendId" | "toId" | "sessionId">>;

interface IGetMsgParams {
  content?: string;
  messageInputDom?: Ref<HTMLElement>;
  aitIds?: number[];
  quotationId?: string;
  files?: IFile[];
}

interface IGetMsg {
  message: IMessage;
  file?: File;
}

interface IMessageStrategy {
  buildMessage(data: Partial<IMessage>): IMessage;

  sendMessage(message: IMessage): void;

  getMsg(params: IGetMsgParams): IGetMsg | null;

  mergeData(data: Partial<IMessage>): IMessage;

  mergeChatObj(data: Partial<IMessage>): IMessage;

  upload(file: File, handel?: UploadProgress): Promise<string | null>;
}

// 抽象基类优化
abstract class BaseMessage implements IMessageStrategy {
  protected readonly messageType: MessageType;
  protected readonly chat = useChat();
  protected readonly user = useUser();

  protected constructor(msgType: MessageType) {
    this.messageType = msgType;
  }

  protected get basicMessage(): IMessage {
    return {
      uuid: GenerateStringUUid(),
      sendId: this.user.userId!,
      toId: 0,
      sessionId: "",
      chatType: ChatType.friend,
      messageType: this.messageType,
      callStatus: CallStatus.None,
      status: MessageStatus.wait,
      updatedAt: new Date().toString(),
      createdAt: new Date().toString(),
    };
  }

  abstract getMsg(params: IGetMsgParams): IGetMsg | null;

  async upload(file: File, handel: UploadProgress = {}): Promise<string | null> {
    try {
      const formData = new FormData();
      formData.append("file", file);
      const res = await upload(formData, handel);
      if (!res || res.status !== 200) throw Error("上传失败，请检查格式");
      return res.data;
    } catch (error) {
      console.error("上传失败:", error);
      return null;
    }
  }

  protected extractImageElement(messageInputDom?: Ref<HTMLElement>): HTMLImageElement | null {
    return messageInputDom?.value?.querySelector("img") ?? null;
  }

  buildMessage(data: MergeDataParams): IMessage {
    if (!this.chat.ChatObject) return this.mergeData(data);
    return this.mergeChatObj(data);
  }

  // 这个必须添加 sendId toId sessionId
  mergeData(data: MergeDataParams): IMessage {
    return { ...this.basicMessage, ...data };
  }

  mergeChatObj(data: Partial<IMessage>): IMessage {
    const { chatType, sessionId, id } = this.chat.ChatObject!;
    const objInfo = chatType === ChatType.group ? { groupId: id } : { toId: id };
    return {
      ...this.basicMessage,
      chatType,
      sessionId,
      ...objInfo,
      ...data,
    };
  }

  sendMessage(message: IMessage): void {
    if (!message) {
      console.warn("不能发送空消息");
      return;
    }
    window.electronApi?.sendMessage(message);
  }
}

// 文本
class TextMessage extends BaseMessage {
  constructor() {
    super(MessageType.text);
  }

  getMsg({ content, quotationId, aitIds }: IGetMsgParams): IGetMsg {
    const { RemoveTag } = useCommon();
    const cleanedContent = RemoveTag(content ?? "");
    const params: Record<string, any> = { content: cleanedContent };
    if (quotationId && quotationId != "") params.quotationId = quotationId;
    if (aitIds && aitIds.length != 0) params.aitIds = JSON.stringify(aitIds);
    const message = this.mergeChatObj(params);
    return { message };
  }
}

// 图片
class ImageMessage extends BaseMessage {
  constructor() {
    super(MessageType.image);
  }

  getMsg({ messageInputDom }: IGetMsgParams): IGetMsg | null {
    const imgEl = this.extractImageElement(messageInputDom);
    if (!imgEl) return null;

    const file = Base64ToFile(imgEl.src);
    // if (CheckFileSize(file)) return null;

    const message = this.mergeChatObj({ fileUrl: imgEl.src });
    return { message, file };
  }
}

// 文件
class FileMessage extends BaseMessage {
  constructor() {
    super(MessageType.file);
  }

  getMsg({ files }: IGetMsgParams): IGetMsg | null {
    if (!files?.length) return null;

    const item = files[0];
    const messageType = item.type === 2 ? MessageType.file : MessageType.image;

    const message = this.mergeChatObj({
      fileUrl: item.viewUrl,
      fileSize: item.file.size,
      fileName: item.file.name,
      messageType,
      localPath: item.file.path,
    });

    return { message, file: item.file };
  }
}

// 图文混合
class MixTxtImgMessage extends BaseMessage {
  constructor() {
    super(MessageType.mixTxtImg);
  }

  getMsg({ content, messageInputDom }: IGetMsgParams): IGetMsg | null {
    const { RemoveTag } = useCommon();
    const cleanedContent = RemoveTag(content ?? "");
    const imgEl = this.extractImageElement(messageInputDom);
    if (!imgEl) return null;

    const file = Base64ToFile(imgEl.src);
    if (CheckFileSize(file)) return null;

    const message = this.mergeChatObj({
      content: cleanedContent,
      fileUrl: imgEl.src,
    });

    return { message, file };
  }
}

// 语音通话消息
class WebRtcVoiceMessage extends BaseMessage {
  constructor() {
    super(MessageType.voiceCall);
  }

  getMsg(): IGetMsg | null {
    return null;
  }
}

// 视频通话消息
class WebRtcVideoMessage extends BaseMessage {
  constructor() {
    super(MessageType.videoCall);
  }

  getMsg(): IGetMsg | null {
    return null;
  }
}

// 好友添加通知
class NotifyRequestAddMessage extends BaseMessage {
  constructor() {
    super(MessageType.requestAdd);
  }

  getMsg(): IGetMsg | null {
    return null;
  }
}

// 撤回消息
class WithdrawMessage extends BaseMessage {
  constructor() {
    super(MessageType.withdraw);
  }

  getMsg(): IGetMsg | null {
    return null;
  }
}

// 引用消息
class QuotationMessage extends BaseMessage {
  constructor() {
    super(MessageType.quotation);
  }
  getMsg({ content, quotationId }: IGetMsgParams): IGetMsg {
    const { RemoveTag } = useCommon();
    const cleanedContent = RemoveTag(content ?? "");
    const message = this.mergeChatObj({ content: cleanedContent, quotationId });
    return { message };
  }
}

// 策略映射
export const MessageStrategyMap: Record<TacticMessageType, IMessageStrategy> = {
  [MessageType.text]: new TextMessage(),
  [MessageType.image]: new ImageMessage(),
  [MessageType.file]: new FileMessage(),
  [MessageType.mixTxtImg]: new MixTxtImgMessage(),
  [MessageType.voiceCall]: new WebRtcVoiceMessage(),
  [MessageType.videoCall]: new WebRtcVideoMessage(),
  [MessageType.requestAdd]: new NotifyRequestAddMessage(),
  [MessageType.withdraw]: new WithdrawMessage(),
  [MessageType.quotation]: new QuotationMessage(),
} as const;
